package com.bwda.dsrs.base.jar.util;

import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.params.KeyParameter;

/**
 *
 *
 * @author system
 * @date 2019/4/26
 */
public class ThreeDesUtil {

	private final static int INT8 = 8;
	private final static int INT2 = 2;
	private final static int INT128 = 123;

	private static final byte[] HEX_DIGITS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70};

	private static final String KEY = "6#dPz>3F";

	private static DESEngine cipher = new DESEngine();

	private static byte[] groupingEncrypt(byte[] key, byte[] data) {
		int iRet = data.length % 8;
		byte[] out;
		if (iRet > 0) {
			int length = data.length + (8 - iRet);
			out = new byte[length];
		} else {
			out = new byte[data.length];
		}
		cipher.init(true, new KeyParameter(key));
		int i;
		for (i = 0; i < data.length / INT8; i++) {
			cipher.processBlock(data, i * 8, out, i * 8);
		}
		if (iRet > 0) {
			byte[] temp = new byte[8];
			System.arraycopy(data, i * 8, temp, 0, iRet);
			temp[iRet] = -128;
			cipher.processBlock(temp, 0, out, i * 8);
		}
		byte[] toasc = new byte[out.length * 2];
		int k = 0;
		int j = 0;
		for (i = 0; i < out.length; i++) {
			k = out[i];
			toasc[j++] = HEX_DIGITS[k >>> 4 & 0xf];
			toasc[j++] = HEX_DIGITS[k & 0xf];
		}

		return toasc;
	}

	private static byte[] groupingDecrypt(byte[] key, byte[] data) {
		int k = 0;
		byte[] tobyte = new byte[data.length / 2];
		for (int i = 0; i < data.length; i += INT2) {
			char ch;
			if (data[i] <= 57){
				ch = (char) (data[i] & 0xf);
			}else {
				ch = (char) ((data[i] & 0xf) + 9);
			}
			ch <<= '\004';
			if (data[i + 1] <= 57){
				ch |= data[i + 1] & 0xf;
			}else{
				ch |= (data[i + 1] & 0xf) + 9;
			}
			tobyte[k] = (byte) ch;
			k++;
		}

		cipher.init(false, new KeyParameter(key));
		if (tobyte.length % INT8 == 0) {
			byte[] out = new byte[tobyte.length];
			for (int i = 0; i < tobyte.length / INT8; i++){
				cipher.processBlock(tobyte, i * 8, out, i * 8);
			}

			int len = padCount(out);
			byte[] deout = new byte[out.length - len];
			System.arraycopy(out, 0, deout, 0, out.length - len);
			return deout;
		} else {
			return null;
		}
	}

	private static int padCount(byte[] in) {
		int count;
		for (count = in.length; count > 0; count--) {
            if (in[count - 1] != 0) {
                break;
            }
        }
		if (in[count - 1] == -INT128){
			return (in.length - count) + 1;
		}else {
			return in.length - count;
		}
	}

	/**
	 * 加密
	 * 
	 * @param code
	 * @return
	 */
	public final static String encode(String code) {
		if (code == null) {
			return null;
		} else {
			byte[] cryptogragh = groupingEncrypt(KEY.getBytes(), code.getBytes());
			return new String(cryptogragh);
		}
	}

	/**
	 * 解密
	 * 
	 * @param code
	 * @return
	 */
	public final static String decode(String code) {
		if (code == null) {
			return null;
		} else {
			byte[] debyte = groupingDecrypt(KEY.getBytes(), code.getBytes());
			return debyte != null ? new String(debyte) : null;
		}
	}

	public static void main(String[] args) {
		System.out.println(ThreeDesUtil.encode("bwda123!@#"));
		System.out.println(ThreeDesUtil.decode("C1FDEF2901ED5251A8C70805021E6D77"));
	}
}
